﻿using HAF.LogUtility.Except;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Net;
using System.Text;

namespace Iptv.MediaReporter.Helper
{
    /// <summary>
    /// 
    /// </summary>
    public class WebHelper
    {
        /// <summary>
        /// 
        /// </summary>
        public static CookieContainer CookieContainers = new CookieContainer();
        /// <summary>
        /// 
        /// </summary>
        public static Dictionary<string, string> Heads = new Dictionary<string, string>();
        //private static HttpWebRequest req4Vender ;
        /// <summary>
        /// 
        /// </summary>
        public static string LastUri { get; set; }

        private static string FireFoxAgent = "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:58.0) Gecko/20100101 Firefox/58.0";
        /// <summary>
        /// 
        /// </summary>
        /// <param name="url"></param>
        /// <param name="method"></param>
        /// <param name="accept"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public static string GetHttpResponse(string url, string method, string accept, string data)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(url))
                {
                    return "HTTP服务错误：URI获取异常！";
                }

                LastUri = string.IsNullOrEmpty(LastUri) ? "https://www.jd.com/" : LastUri;

                HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
                req.KeepAlive = true;
                req.Method = method.ToUpper();
                req.AllowAutoRedirect = true;
                req.CookieContainer = CookieContainers;
                //下面语句可能导致：远程服务器返回错误: (415) unsupported media type.
                req.ContentType = string.IsNullOrEmpty(accept) ? "multipart/related" : accept;
                req.UserAgent = FireFoxAgent;
                req.Accept = string.IsNullOrEmpty(accept) ? "application/xop+xml" : "*/*";
                req.Headers.Add("Accept-Encoding", "gzip, deflate, br");
                if (Heads.Count > 0)
                {
                    foreach (var item in Heads)
                    {
                        req.Headers.Add(item.Key, item.Value);
                    }
                }
                req.Referer = LastUri;
                //以下语句报异常：{"必须使用适当的属性或方法修改“Host”标头。\r\n参数名: name"} 
                //HOST为只读属性，在创建WebRequest时根据uri直接生成
                //req4Vender.Headers.Add("Host", "mall.jd.com");
                //req.Timeout = 50 * 1000;
                req.Timeout = 2 * 60 * 1000;
                //http中最常见的2个header的区别
                //Content - Type:application / json; charset = UTF - 8
                //Accept: application / json; charset = UTF - 8

                //Content - Type 用于描述本次请求的body的内容是json格式，且编码为UTF - 8
                //Accept 用于描述客户端希望返回的结果以json来组织，且UTF - 8
                //Content - Type 用于描述request,而Accept用于描述reponse

                if (method.ToUpper() == "POST" && !string.IsNullOrWhiteSpace(data))
                {
                    ASCIIEncoding encoding = new ASCIIEncoding();
                    byte[] postBytes = encoding.GetBytes(data); ;
                    req.ContentLength = postBytes.Length;
                    Stream st = req.GetRequestStream();
                    st.Write(postBytes, 0, postBytes.Length);
                    st.Close();
                }

                System.Net.ServicePointManager.ServerCertificateValidationCallback += (se, cert, chain, sslerror) =>
                {
                    return true;
                };

                string strRes = string.Empty;
                using (HttpWebResponse res = (HttpWebResponse)req.GetResponse())
                {
                    if (res.StatusCode == HttpStatusCode.OK)
                    {
                        //响应内容字符集判断
                        Encoding encode = encode = new UTF8Encoding(false);
                        //Encoding.Default;
                        //if (res.ContentType.ToUpper().IndexOf("UTF") > 0)
                        //{
                        //    encode = new UTF8Encoding(false);
                        //}
                        //else
                        //{
                        //    encode = System.Text.Encoding.GetEncoding("gb2312"); ;
                        //}
                        CookieContainers.Add(res.Cookies);
                        strRes = GetResponseBody(res, encode);

                        //using (Stream resst = res.GetResponseStream())
                        //{
                        //    StreamReader sr = new StreamReader(resst, encode);
                        //    str = sr.ReadToEnd();
                        //    sr.Close();
                        //}
                    }
                    else
                    {
                        var message = String.Format("Request failed. Received HTTP {0}", res.StatusCode);
                        throw new ApplicationException(message);
                    }
                }

                LastUri = url;
                return strRes;
            }
            catch (Exception ex)
            {
                throw new Exception(string.Format("URI请求异常：{0}", url), ex);
            }
        }
        /// <summary>
        /// 获取响应数据
        /// </summary>
        /// <param name="response">响应对象</param>
        /// <param name="encode">字符集</param>
        /// <returns>响应数据</returns>
        private static string GetResponseBody(HttpWebResponse response, Encoding encode)
        {
            string responseBody = string.Empty;
            if (response.ContentEncoding.ToLower().Contains("gzip"))
            {
                using (GZipStream stream = new GZipStream(response.GetResponseStream(), CompressionMode.Decompress))
                {
                    using (StreamReader reader = new StreamReader(stream, encode))
                    {
                        responseBody = reader.ReadToEnd();
                        reader.Close();
                    }
                }
            }
            else if (response.ContentEncoding.ToLower().Contains("deflate"))
            {
                using (DeflateStream stream = new DeflateStream(response.GetResponseStream(), CompressionMode.Decompress))
                {
                    using (StreamReader reader = new StreamReader(stream, encode))
                    {
                        responseBody = reader.ReadToEnd();
                        reader.Close();
                    }
                }
            }
            else
            {
                using (Stream stream = response.GetResponseStream())
                {
                    using (StreamReader reader = new StreamReader(stream, encode))
                    {
                        responseBody = reader.ReadToEnd();
                        reader.Close();
                    }
                }
            }

            return responseBody;
        }

        /// <summary>
        /// 获取远端文件
        /// </summary>
        /// <param name="url">文件远端地址</param>
        /// <param name="localPath">本地存储地址</param>
        /// <returns>是否成功</returns>
        public static bool GetRemoteFile(string url, string localPath)
        {
            bool isDown = false;
            if (string.IsNullOrWhiteSpace(url))
            {
                throw new RunException(RunCode.AddressErr, url);
            }
            try
            {
                HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
                req.KeepAlive = true;
                req.Method = "GET";
                req.AllowAutoRedirect = true;
                req.UserAgent = FireFoxAgent;
                req.Accept = "*/*";
                //req.TransferEncoding
                req.Timeout = 50000;
                System.Net.ServicePointManager.ServerCertificateValidationCallback += (se, cert, chain, sslerror) =>
                {
                    return true;
                };

                string strRes = string.Empty;
                using (HttpWebResponse res = (HttpWebResponse)req.GetResponse())
                {
                    if (res.StatusCode == HttpStatusCode.OK)
                    {
                        using (Stream resst = res.GetResponseStream())
                        {
                            //创建本地文件写入流
                            using (Stream fs = new FileStream(localPath, FileMode.Create))
                            {
                                byte[] bArr = new byte[1024];
                                int size = resst.Read(bArr, 0, (int)bArr.Length);
                                while (size > 0)
                                {
                                    fs.Write(bArr, 0, size);
                                    size = resst.Read(bArr, 0, (int)bArr.Length);
                                }

                                isDown = true;
                            }
                        }
                    }
                    else
                    {
                        var message = String.Format("Request failed. Received HTTP Error Code {0}", res.StatusCode);
                        throw new RunException(RunCode.Error, message);
                    }
                }
                return isDown;
            }
            catch (Exception ex)
            {
                throw new Exception(string.Format("URI请求异常：{0}", url), ex);
            }
        }
    }
}
